home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
355_02
/
slk2.exe
/
SPP
/
ST.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-09
|
6KB
|
269 lines
/*
Sherlock preprocessor -- symbol table routines.
Block-structured version.
source: st.c
started: November 4, 1985
version: December 4, 1987;
February 10, 1989 put better tracing in st_lookup.
April 16, 1990: fix bugs in st_enter and st_init.
PUBLIC DOMAIN SOFTWARE
Sherlock, including the SPP, SDEL and SDIF programs, was placed in
the public domain on June 15, 1991, by its author,
Edward K. Ream
166 North Prospect Ave.
Madison, WI 53705.
(608) 257-0802
Sherlock may be used for any commercial or non-commercial purpose.
DISCLAIMER OF WARRANTIES
Edward K. Ream (Ream) specifically disclaims all warranties,
expressed or implied, with respect to this computer software,
including but not limited to implied warranties of merchantability
and fitness for a particular purpose. In no event shall Ream be
liable for any loss of profit or any commercial damage, including
but not limited to special, incidental consequential or other damages.
*/
#include "spp.h"
/* Define static routines. */
static int st_hash(char *s);
/*
Define the format of symbol table nodes.
*/
#define ST_PRIME 101
typedef struct st_node symtab;
static struct st_node {
symtab * st_next;
symtab * st_back;
symtab * st_lnext;
int st_leveln;
char * st_name;
en_tokens st_type; /* type for printf */
bool st_tdflag; /* typedef flag */
};
static symtab st_ht [ST_PRIME]; /* The hash table. */
/*
Define the list of symbol tables.
*/
typedef struct level_node level;
static struct level_node {
level * lev_next;
symtab * lev_lnext;
int lev_leveln;
};
static level level_head = {NULL, NULL, 0}; /* Head of the list of tables. */
static int cur_level = 0;
/* ========== Debugging routines ========== */
/*
Dump all symbols of both symbol tables.
*/
#ifdef BUG
void
st_dump()
{
TICK("st_dump");
}
#endif /* BUG */
/*
Enter a new level of the symbol table.
*/
void
st_begin(void)
{
level * lp;
TRACEP("st_begin", printf("cur_level = %d\n", cur_level+1));
cur_level++;
lp = m_alloc(sizeof(level));
lp -> lev_next = level_head . lev_next;
level_head . lev_next = lp;
lp -> lev_lnext = NULL;
lp -> lev_leveln = cur_level;
}
/*
Exit a level of the symbol table.
*/
void
st_end(void)
{
symtab * sp, * next, * back;
level * lp;
TICK("st_end");
if (cur_level <= 0) {
syserr("st_end: cur_level <= 0");
}
lp = level_head . lev_next;
if (lp == NULL) {
syserr("st_end: NULL level node");
}
/* Unlink and deallocate all st_nodes at this level. */
for (sp = lp -> lev_lnext; sp; sp = next) {
/* Unlink the node from the bucket list. */
back = sp -> st_back;
next = sp -> st_next;
back -> st_next = next;
if (next) {
next -> st_back = back;
}
/* Deallocate the st_node. */
m_free(sp);
}
/* Unlink the level node. */
level_head . lev_next = lp -> lev_next;
m_free(lp);
cur_level--;
}
/*
Place a symbol at the start of the hash list.
This will insure that any new definition hides previous defs.
*/
void
st_enter (char *symbol, en_tokens type, bool td_flag)
{
register symtab * p;
register level * lp;
int hash;
TRACEP("st_enter", printf("(%s, %s, %d)\n",
symbol, pr_op(type), td_flag));
if (symbol == NULL) {
error("st_enter: internal: NULL symbol");
symbol = "";
return;
}
/* Dynamically allocate space for node. */
p = m_alloc(sizeof(symtab));
/* Hang node from hash table. */
hash = st_hash(symbol);
p -> st_next = st_ht [hash] . st_next;
p -> st_back = &st_ht [hash];
st_ht [hash] . st_next = p;
/* Link the node to the level list. */
lp = level_head . lev_next;
p -> st_lnext = lp -> lev_lnext;
lp -> lev_lnext = p;
p -> st_leveln = cur_level;
/* Fill in the name and type. */
p -> st_type = type;
p -> st_name = str_alloc(symbol);
p -> st_tdflag = td_flag;
}
/*
Compute the hash function for a local symbol.
*/
static int
st_hash (sym)
register char * sym;
{
register int hash;
TRACEP("st_hash", printf("(%s)\n", sym));
for (hash = 0; *sym; ) {
hash *= 3;
hash += (int) *sym++;
hash %= ST_PRIME;
}
TRACEPN("st_hash", printf("returns: %d\n", hash));
return hash;
}
/*
Initialize the symbol tables for the very first time.
*/
void
st_init(void)
{
int i;
register symtab *p;
TICK("st_init");
/* Initialize the hash table. */
for(i = 0; i < ST_PRIME; i++) {
p = & st_ht [i];
p -> st_next = NULL;
p -> st_back = NULL;
p -> st_lnext = NULL;
p -> st_leveln = 0;
p -> st_name = "<header>";
}
/* bug fix: 4/16/90
Required so st_enter doesn't dereference a NULL pointer.
*/
st_begin();
}
/*
Look up a symbol in the local symbol table.
Return a type token.
*/
bool
st_lookup (register char * symbol, en_tokens * type, bool * td_flag)
{
register symtab * sp;
int hash;
TRACEP("st_lookup", printf("(%s)\n", symbol));
/* Search down the list of st_nodes. */
hash = st_hash(symbol);
for (sp = st_ht [hash] . st_next; sp; sp = sp -> st_next) {
TRACEN("v", printf("compare with <%s>\n", sp -> st_name));
if(str_eq(symbol, sp -> st_name)) {
TRACEPN("st_lookup",
printf("sets *type = %s, ",
pr_op(sp -> st_type));
printf("*td_flag = %d\n", sp -> st_tdflag));
*type = sp -> st_type;
*td_flag = sp -> st_tdflag;
return TRUE;
}
}
TRACEPN("st_lookup", printf("not found\n"));
return FALSE;
}